home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / util / libs / graphics3d.lha / src / library / graphics3df_g.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-16  |  13.4 KB  |  587 lines

  1. /*
  2. **      $VER: graphics3Df_i.c 10.10 (16.02.98)
  3. **
  4. **      Internal functions for graphics3D.library
  5. **
  6. **      (C) Copyright 97 Patrizio Biancalani
  7. **      All Rights Reserved.
  8. **
  9. **    Note: this code is traslate from the blitzbasic 3d graphics engine 
  10. **          V 0.9 of Maciej R. Gorny.
  11. */
  12.  
  13. #include <exec/types.h>
  14. #include <exec/memory.h>
  15. #include <proto/exec.h>
  16. #include <proto/intuition.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/screens.h>
  19.  
  20. #include <graphics/rastport.h>
  21. #include <graphics/clip.h>
  22. #include <graphics/regions.h>
  23. #include <graphics/gfx.h>
  24. #include <graphics/gfxmacros.h>
  25. #include <graphics/layers.h>
  26.  
  27. #include "graphics3Dc.h"
  28. #include "graphics3D.h"
  29. #include "graphics3d2d.h"
  30. #include "graphics3d2d_proto.h"
  31.  
  32. /*** funzioni esterne solo matematiche ***/
  33. extern void matidentity4x4(struct matrix4x4 *imatrix); 
  34. extern void matzero4x4(struct matrix4x4 imatrix);
  35. extern void matcopy4x4(struct matrix4x4 *s_m,struct matrix4x4 *d_m);
  36. extern void matmult4x4(struct matrix4x4 *a,struct matrix4x4 *b,
  37.         struct matrix4x4 *r);
  38. extern void matmult4x4s(struct matrix4x4 *a,struct matrix4x4 *b,
  39.         struct matrix4x4 *r);
  40. extern void matmult1x4s(struct matrix1x4 *a,struct matrix4x4 *b,
  41.         struct matrix1x4 *r);
  42. extern void makevector3d(struct vertex *a,struct vertex *b,
  43.          struct vector *result);
  44. extern long int vectormag3d(struct vector *a);
  45. extern void normalpol(struct vertex *v0,struct vertex *v1,
  46.      struct vertex *v2,struct vector *normal);
  47. extern long int dotproduct(struct vector *u,struct vector *v);
  48. extern long int sqri(long int v);
  49. extern long int abs(long int val);
  50. extern struct objectnode *pobj(struct ambient3d *in);
  51. extern struct objectnode *resetobj(struct ambient3d *in);
  52. extern struct objectnode *nextobj(struct ambient3d *in);
  53.  
  54.  
  55. /******************************************************/
  56. /** rimuove le facce posteriori dell'oggetto corrente**/
  57. /** e calcola il flat shading dell'oggetto           **/
  58. /******************************************************/
  59. void removebackfacesandshade(in)
  60. struct ambient3d *in;
  61. {
  62. struct objectnode *obj;
  63. struct vector *vp, *ls;
  64. struct vert1 *v0,*v1,*v2,*v3;
  65. struct polygon *pol;
  66. long int ms1,ms,al,sha_org,shading,curr_poly,dp,intensity;
  67. struct vector u,v;
  68. struct vector normal,norm,sight;
  69. long int norml;
  70. char col;
  71. #ifdef DEBUG
  72. char dbg[80];
  73. #endif
  74.  
  75. vp=&in->view_point;
  76. ls=&in->light_source;
  77. obj=pobj(in);
  78. shading=0x0F & obj->shade;
  79. sha_org=shading;
  80.  
  81. ms=in->maxintensity;
  82. ms1=ms << SFIXV;
  83. al=in->ambient_light >> SFIXV;
  84. for (curr_poly=0; curr_poly<obj->numpolys; curr_poly++)
  85.    {
  86. #ifdef DEBUG
  87. sprintf(dbg,"polig=%ld\n",curr_poly);
  88. write_dbg(dbg);
  89. #endif
  90.    shading=sha_org;
  91.    col=0;
  92.    pol=&obj->polys[curr_poly];       
  93.    pol->visible=1;
  94.    if (pol->active==NULL) pol->visible=0;
  95.    v0=&obj->vcamera[pol->vertexlist0];
  96.    v1=&obj->vcamera[pol->vertexlist1];
  97.    v2=&obj->vcamera[pol->vertexlist2];
  98.    v3=&obj->vcamera[pol->vertexlist3];
  99.    if (pol->numpoints>2 AND pol->active)
  100.     {
  101.     if (shading==FLAT OR shading==GORAUD OR pol->twosided==NULL)
  102.         {
  103.     /* se poligono a 1 faccia o flat o goraud shading calcolo normale al poligono */
  104.         normalpol(v0,v1,v2,&normal);    
  105.         }
  106.     if (pol->twosided==NULL)
  107.         {
  108.     /* test per poligoni ad una faccia se visibili o meno */
  109.         sight.x=vp->x - v0->x;
  110.         sight.y=vp->y - v0->y;
  111.         sight.z=vp->z - v0->z;
  112.     
  113.         if (dotproduct(&normal,&sight)<NULL) pol->visible=0;
  114.         }
  115.     }
  116.    if (pol->visible>NULL AND pol->numpoints>2)
  117.     {
  118.     switch(shading)
  119.         {
  120.         case(GORAUD):
  121.         case(FLAT):
  122.     /* calcolo lunghezza normale poligono */
  123.             dp=dotproduct(&normal,ls);
  124. /*            if (pol->twosided!=NULL AND dp<NULL) dp=-dp;*/
  125.             if (dp>NULL)
  126.                 {
  127.                 norml=vectormag3d(&normal);
  128.                 if (norml==NULL) norml=1;
  129.                 intensity=al+(ms1*dp)/norml;
  130.                 if (intensity>ms) intensity=ms;
  131.                 if (intensity<0) intensity=0;
  132.         /* intensity e' compreso ora tra 0 e ms ,si usera' questo valore */
  133.         /* per trovare l'indice di sfumatura */
  134.                 col=intensity;
  135. #ifdef DEBUG
  136. sprintf(dbg,"pol.col=%ld inte=%ld\n",pol->color,intensity);
  137. write_dbg(dbg);
  138. #endif
  139.                 }
  140.             else
  141.                 {
  142. #ifdef DEBUG
  143. sprintf(dbg,"pol.col=%ld luce=%ld\n",pol->color,al);
  144. write_dbg(dbg);
  145. #endif
  146.                 col=al;
  147.                 }
  148.             if (shading==GORAUD)
  149.                 {
  150.                 v0->color+=col;
  151.                 v1->color+=col;
  152.                 if (v0->npol==NULL) v0->color=col;
  153.                 if (v1->npol==NULL) v1->color=col;        
  154.                 v0->npol+=1;
  155.                 v1->npol+=1;
  156.                 if (pol->numpoints>2)
  157.                     {
  158.                     v2->color+=col;
  159.                     if (v2->npol==NULL) v2->color=col;
  160.                     v2->npol+=1;
  161.                     }
  162.                 if (pol->numpoints>3)
  163.                     {
  164.                     v3->color+=col;
  165.                     if (v3->npol==NULL) v3->color=col;
  166.                     v3->npol+=1;
  167.                     }
  168.                 }
  169.             break;
  170.  
  171.         case(SOLID):
  172.             col=(ms>>1);
  173.             break;
  174.     
  175.         default:
  176.     /* se tipo di shading <> da goraud,flat e solid si assume cosi' */
  177.             col=0;
  178.         }
  179.     }
  180.    pol->shade=col;
  181.    }
  182.  
  183. }
  184.  
  185. /******************************************************/
  186. /** crea la lista di tutti i poligoni visibili nella **/
  187. /** frame corrente e li memorizza gia' proiettati    **/
  188. /** e' gia' stato ottimizzato il piu' possibile.     **/
  189. /** Ora si calcola la distanza tra il punto medio del**/
  190. /** poligono e l'osservatore per il succ. riordino.  **/
  191. /******************************************************/
  192. void generatepolylist(in)
  193. struct ambient3d *in;
  194. {
  195. long int *iwp;
  196. long int zx,zy,zxp,zyp,id,fix1,fix,curr_poly,i,ii,mx,my,mz,x,y,z;
  197. struct pixel *pt;
  198. struct objectnode *obj;
  199. struct vert1 *vc;
  200. struct polygon *pol;
  201. struct polytemp *wpl;
  202.  
  203. #ifdef DEBUG
  204. char dbg[100];
  205. #endif
  206.  
  207. if (in->iwpolys==NULL) return(0);
  208.  
  209. iwp=in->iwpolys;
  210. pt=(struct pixel *)in->temp;
  211.  
  212. #ifdef DEBUG
  213. sprintf(dbg,"pt=%ld\n",pt);
  214. write_dbg(dbg);
  215. #endif
  216.  
  217. obj=resetobj(in);
  218. id=0;
  219. curr_poly=0;
  220. fix=(in->aspect_ratio*in->viewing_distance) >> SFIXV;
  221. fix1=in->aspect_ratio;
  222. zy=(fix*in->zoom) >> SFIXV;
  223. zx=(in->viewing_distance*in->zoom) >> SFIXV;
  224. zxp=in->zoom;
  225. zyp=(in->aspect_ratio*in->zoom) >> SFIXV;
  226.  
  227. #ifdef DEBUG
  228. sprintf(dbg,"\n--- ciclo generatepolylist ---\n");
  229. write_dbg(dbg);
  230. sprintf(dbg,"view distance=%ld fix=%ld\n",in->viewing_distance,fix);
  231. write_dbg(dbg);
  232. #endif
  233.  
  234. do 
  235.    {    
  236.    if (obj->clipped==0 AND obj->state!=0) 
  237.     {
  238.     /* se goraud shading e se non gia fatto normalizzo intensita' colori vertici */
  239.     if ((0x0F & obj->shade)==GORAUD)
  240.         {
  241.         for(i=0 ;i<obj->numverts ;i++)
  242.             {
  243.             vc=&obj->vcamera[i];
  244.             if (vc->npol!=NULL)
  245.                 {
  246. #ifdef DEBUG
  247. sprintf(dbg,"vert#%ld col=%ld npol=%ld\n",i,vc->color,vc->npol);
  248. write_dbg(dbg);
  249. #endif
  250.                 vc->color=vc->color/vc->npol;
  251.                 vc->npol=0;
  252. #ifdef DEBUG
  253. sprintf(dbg,"col=%ld npol=%ld\n",vc->color,vc->npol);
  254. write_dbg(dbg);
  255. #endif
  256.                 }
  257.             }
  258.         }
  259.     /** proietto tutti i punti dell'oggetto corrente **/
  260.     switch(in->projection_type)
  261.         {
  262.         case(PROSP_P) :
  263.     /* uso proiezione prospettica */
  264.             for(i=0 ;i<obj->numverts ;i++ ) 
  265.                 {
  266.                 vc=&obj->vcamera[i];
  267.                 z=vc->z;
  268.                 if (z==NULL) z=1;
  269. /*
  270. #ifdef DEBUG
  271. sprintf(dbg,"Vertex=%ld\n",i);
  272. write_dbg(dbg);
  273. sprintf(dbg,"x=%ld y=%ld z=%ld z=%ld\n",vc->x,vc->y,vc->z,z);
  274. write_dbg(dbg);
  275. sprintf(dbg,"half_screen_w=%ld half_screen_h=%ld zx=%ld zy=%ld\n",in->half_screen_width,
  276.     in->half_screen_height,zx,zy);
  277. write_dbg(dbg);
  278. #endif
  279. */
  280.                 x=in->half_screen_width +
  281.                      (vc->x*zx)/z;
  282.                 y=in->half_screen_height -
  283.                      (vc->y*zy)/z;
  284.                 if (x>16355) x=16355;
  285.                 if (x<-16355) x=-16355;
  286.                 if (y>16355) y=16355;
  287.                 if (y<-16355) y=-16355;
  288.                 pt[i].x=x;
  289.                 pt[i].y=y;
  290. /*
  291. #ifdef DEBUG
  292. sprintf(dbg,"xp=%ld yp=%ld \n",pt[i].x,pt[i].y);
  293. write_dbg(dbg);
  294. #endif
  295. */        
  296.                 }
  297.                 break;
  298.         case(PARAL_P) :
  299.     /* uso proiezione parallela */
  300.             for(i=0 ;i<obj->numverts ;i++ ) 
  301.                 {
  302.                 vc=&obj->vcamera[i];
  303.                 pt[i].x=in->half_screen_width + 
  304.                     ((vc->x*zxp) >> (2*SFIXV));
  305.                 pt[i].y=in->half_screen_height + 
  306.                     ((vc->y*zyp) >> (2*SFIXV));
  307.                 if (x>16355) x=16355;
  308.                 if (x<-16355) x=-16355;
  309.                 if (y>16355) y=16355;
  310.                 if (y<-16355) y=-16355;
  311.                 pt[i].x=x;
  312.                 pt[i].y=y;
  313.                 }
  314.                 break;
  315.         }
  316.     /* genero lista di poligoni gia' proiettati */
  317.     vc=obj->vcamera;
  318.     for(curr_poly=0 ;curr_poly<obj->numpolys ;curr_poly++) 
  319.         {
  320.         pol=&obj->polys[curr_poly];
  321.         if (pol->visible!=NULL AND pol->clipped==NULL)
  322.             {
  323.     /* reinizializzo puntatore a indice su lista poligoni */
  324.     /* per velocizzare il successivo riordino          */
  325.             if (id < in->max_polys)
  326.                {
  327.                wpl=&in->worldpolys[id];
  328.                iwp[id]=(long int )wpl;
  329.                mz=0;
  330.                mx=0;
  331.                my=0;
  332.                wpl->numpoints=pol->numpoints;
  333.                wpl->color=pol->color;
  334.                wpl->shade=pol->shade;
  335.                wpl->vmode=obj->shade;        
  336.                wpl->obj=obj->id;    
  337.                wpl->npol=curr_poly;
  338.                wpl->tmap=&pol->ptmap;    
  339.                i=pol->vertexlist0;
  340.                wpl->x1=pt[i].x;
  341.                wpl->y1=pt[i].y;
  342.                wpl->clp1=vc[i].color;
  343.                wpl->z1=vc[i].z;
  344.                mz+=wpl->z1;
  345.                mx+=wpl->x1;
  346.                my+=wpl->y1;    
  347.  
  348.                if (pol->numpoints>=2)            
  349.                 {
  350.                 i=pol->vertexlist1;
  351.                 wpl->x2=pt[i].x;
  352.                 wpl->y2=pt[i].y;
  353.                 wpl->clp2=vc[i].color;
  354.                 wpl->z2=vc[i].z;
  355.                 mz+=wpl->z2;
  356.                    mx+=wpl->x2;
  357.                    my+=wpl->y2;    
  358.                 }
  359.  
  360.                if (pol->numpoints>=3)        
  361.                 {
  362.                 i=pol->vertexlist2;
  363.                 wpl->x3=pt[i].x;
  364.                 wpl->y3=pt[i].y;
  365.                 wpl->clp3=vc[i].color;
  366.                 wpl->z3=vc[i].z;
  367.                    mz+=wpl->z3;
  368.                    mx+=wpl->x3;
  369.                    my+=wpl->y3;    
  370.             
  371.                 wpl->x4=wpl->x1;
  372.                 wpl->y4=wpl->y1;    
  373.                 }
  374.  
  375.                if (pol->numpoints==4) 
  376.                 {
  377.                 i=pol->vertexlist3;
  378.                 wpl->x4=pt[i].x;
  379.                 wpl->y4=pt[i].y;
  380.                 wpl->clp4=vc[i].color;
  381.                 wpl->z4=vc[i].z;
  382.                    mz+=wpl->z4;
  383.                    mx+=wpl->x4;
  384.                    my+=wpl->y4;    
  385.  
  386.                 wpl->x5=wpl->x1;
  387.                 wpl->y5=wpl->y1;
  388.                 }
  389.     /* calcolo punto medio del poligono */
  390.                ii=pol->numpoints << SFIXV;
  391.                mx/=ii;
  392.                my/=ii;
  393.                mz/=ii;
  394.     /* quindi calcolo distanza media poligono (evito la radice ,non serve)*/
  395.                wpl->svalue=mx*mx + my*my + mz*mz;
  396. /*
  397. #ifdef DEBUG
  398. sprintf(dbg,"dist=%ld\n",wpl->svalue);
  399. write_dbg(dbg);
  400. #endif
  401. */
  402.                id+=1;
  403.                }
  404.             }
  405.         }
  406.     }
  407.    obj=nextobj(in);
  408.    }while(obj!=NULL);
  409.  
  410. in->total_polys=id;
  411.  
  412. /********************/
  413. }
  414.  
  415. /************************************
  416.  ** routin richiamata da quicksort **
  417.  ** occhio e' recursiva.       **
  418.  ** I parametri non possono percio'**
  419.  ** essere passati tramite registri**
  420.  ************************************/
  421. void qsort(lo0,hi0,pol,count)
  422. long int lo0;
  423. long int hi0;
  424. long int *pol;
  425. long int *count;
  426. {
  427. long int it, lo, hi, mid, t;
  428. struct polytemp *wpl;
  429.  
  430. lo=lo0;
  431. hi=hi0;
  432. it=count[0];
  433.  
  434. if (hi0>lo0)
  435. /* stabilisco arbitrariamente il pivot point nel mezzo dell'array */
  436.     {
  437.     wpl=(struct polytemp *)pol[(lo0+hi0)>>1];
  438.     mid=wpl->svalue;
  439.  
  440. /* eseguo il loop finche non incrocio indici */
  441.     while(lo<=hi)
  442. /* trovo il primo elemento minore o uguale a mid partendo da sinistra */
  443.         {
  444.         wpl=(struct polytemp *)pol[lo];
  445.         while(lo<hi0 AND wpl->svalue>mid)
  446.             {
  447.             lo++;
  448.             wpl=(struct polytemp *)pol[lo];
  449.             it++;
  450.             }
  451. /* trovo il primo elemento maggiore o uguale a mid partendo da destra */
  452.         wpl=(struct polytemp *)pol[hi];
  453.         while(hi>lo0 AND wpl->svalue<mid)
  454.             {    
  455.             hi--;
  456.             wpl=(struct polytemp *)pol[hi];
  457.             it++;
  458.             }
  459. /* se gli indici non si sono incrociati scambio elementi */
  460.         if (lo<=hi)
  461.             {
  462.             t=pol[hi];
  463.             pol[hi]=pol[lo];
  464.             pol[lo]=t;
  465.             lo++;
  466.             hi--;
  467.             }
  468.         }
  469.     }        
  470.  
  471. count[0]=it;
  472.  
  473. if (lo0<hi) qsort(lo0,hi,pol,count);
  474.  
  475. if (lo<hi0) qsort(lo,hi0,pol,count);
  476.  
  477. }
  478.  
  479. /******************************************************
  480.  ** visualizza un gruppo di poligoni nella rastport  **
  481.  ** corrente(purche di 3 o 4 lati).              **    
  482.  ** E' ottimizzata il piu' possibile.             **
  483.  ******************************************************
  484.  **** INPUT :                         ** 
  485.  **  amb ->valore non 0 ritornato da GD_display3d(). **
  486.  **  iwp  ->puntatore ad array di puntatori a strut- **
  487.  **         ture polytemp.                 ** 
  488.  **  total_polys ->n# totale elementi nell'array iwp **
  489.  **  colb ->se >=0 allora poligoni con bordo di quel **
  490.  **         colore.                     **
  491.  **** OUTPUT:                         **
  492.  ** nessuno.                         **
  493.  ******************************************************/
  494. void paintpol(amb,iwp,total_polys,colb)
  495. struct ambient3d *amb;
  496. long int *iwp;
  497. long int total_polys;
  498. long int colb;
  499. {
  500. struct RastPort *rast;
  501. struct polytemp *wpl;
  502. long int i,f;
  503.  
  504. #ifdef DEBUG
  505. char dbg[100];
  506. #endif
  507.  
  508. if (amb->iwpolys==NULL) return(0);
  509.  
  510. rast=amb->graf->rast;
  511. f=rast->FgPen;
  512.  
  513. #ifdef DEBUG
  514. sprintf(dbg,"ambient3d=%ld rast=%ld\n",amb,rast);
  515. write_dbg(dbg);
  516. #endif
  517.  
  518. for (i=0;i<total_polys;i++)
  519.     {
  520.     wpl=(struct polytemp *)iwp[i];
  521.     /* visualizzo il poligono */ 
  522. /** visualizza un poligono proiettato **/
  523.     switch(wpl->numpoints)
  524.         {
  525.         case (1) :
  526.     /* 1 vertice -> disegno un punto */
  527.             pixel(amb,wpl);
  528.             break;
  529.         case (2) :
  530.     /* 2 vertici -> disegno una linea */
  531.             line(amb,wpl);
  532.             break;
  533.         case (3) :
  534.     /* 3 vertici -> poligono triangolare disegno in base a wpl->vmode */
  535.             if ((wpl->vmode & 0x0F)!=WIREF)
  536.                 {
  537.                 drw_tg(amb,wpl,colb);
  538.                 }
  539.             else
  540.                 {
  541.                 line(amb,wpl);
  542.                 }
  543.             break;
  544.         case (4) :
  545.     /* 4 vertici -> poligono quadrangolare disegno in base a wpl->vmode*/
  546.             if ((wpl->vmode & 0x0F)!=WIREF)
  547.                 {
  548.                 drw_qg(amb,wpl,colb);
  549.                 }
  550.             else
  551.                 {
  552.                 line(amb,wpl);
  553.                 }
  554.             break;
  555.         }
  556.     }
  557.  
  558. SetAPen(rast,f);
  559. }
  560.  
  561. /**********************************************
  562.  ** effettuo ordinamento poligoni proiettati **
  563.  ** via quicksort                 **
  564.  ** mediamente 4 volte piu' veloce dello     ** 
  565.  ** shellsort.                     **
  566.  **********************************************
  567.  **** INPUT :                     **
  568.  ** len -> numero di poligoni da riordinare  **
  569.  ** pol -> array di puntatori alle strutture **
  570.  **        polytemp, da riordinare.          **
  571.  **** OUTPUT:                     **
  572.  ** n# di passi effettuati per l'ordinamento.** 
  573.  **********************************************/
  574. long int quicksort(len,pol)
  575. long int len;
  576. long int *pol;
  577. {
  578. long int itera;
  579.  
  580. itera=0;
  581.  
  582. if (len>NULL) qsort(0,len-1,pol,&itera);
  583.  
  584. return(itera);
  585. }
  586. /*******************************************************************/
  587.